/*
 * Copyright (C) 2017-2025
 * ZKMall All rights reserved, Designed By 深圳中科鑫智科技有限公司
 * Copyright authorization contact 18814114118
 */
package com.shop.zkmall.app.controller.index;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.shop.zkmall.app.domain.req.LikeReq;
import com.shop.zkmall.app.im.TxTemplate;
import com.shop.zkmall.app.redis.service.api.impl.RedisService;
import com.shop.zkmall.commons.cache.constants.CacheKeyConstants;
import com.shop.zkmall.commons.result.R;
import com.shop.zkmall.web.annotation.NoRepeatSubmit;
import com.shop.zkmall.app.page.index.Index;
import com.shop.zkmall.app.page.index.Product;
import com.shop.zkmall.app.page.login.BuyerUser;
import com.shop.zkmall.app.page.login.TokenInfoBo;
import com.shop.zkmall.app.param.buyer.BuyerGetCodeParam;
import com.shop.zkmall.app.param.check.CheckShopParam;
import com.shop.zkmall.app.param.index.DictGetSelectParam;
import com.shop.zkmall.app.param.index.IndexParam;
import com.shop.zkmall.app.param.index.LoginParam;
import com.shop.zkmall.app.param.index.LoginPhoneParam;
import com.shop.zkmall.app.param.index.RefreshTokenParam;
import com.shop.zkmall.app.param.index.SearchParam;
import com.shop.zkmall.app.param.index.UpdateAliPhoneParam;
import com.shop.zkmall.app.param.index.UpdateWxPhoneParam;
import com.shop.zkmall.app.redis.service.api.UserRedisService;
import com.shop.zkmall.app.service.buyer.CereBuyerSearchService;
import com.shop.zkmall.app.service.buyer.CereBuyerUserService;
import com.shop.zkmall.app.service.dict.CerePlatformDictService;
import com.shop.zkmall.app.service.index.IndexService;
import com.shop.zkmall.app.service.product.CereProductSkuService;
import com.shop.zkmall.app.service.shop.CerePlatformShopService;
import com.shop.zkmall.app.utils.WechatUtil;
import com.shop.zkmall.commons.constant.CoReturnFormat;
import com.shop.zkmall.commons.constant.IntegerEnum;
import com.shop.zkmall.commons.domain.buyer.CereBuyerSearch;
import com.shop.zkmall.commons.domain.buyer.CereBuyerUser;
import com.shop.zkmall.commons.domain.common.Page;
import com.shop.zkmall.commons.domain.dict.CerePlatformDict;
import com.shop.zkmall.commons.domain.product.CereProductSku;
import com.shop.zkmall.commons.domain.shop.CerePlatformShop;
import com.shop.zkmall.commons.exception.CoBusinessException;
import com.shop.zkmall.commons.result.Result;
import com.shop.zkmall.commons.utils.EmptyUtils;
import com.shop.zkmall.commons.utils.EncryptUtil;
import com.shop.zkmall.commons.utils.HttpUtils;
import com.shop.zkmall.commons.utils.RandomStringUtil;
import com.shop.zkmall.commons.utils.TimeUtils;
import com.shop.zkmall.commons.utils.ValidationUtil;
import com.shop.zkmall.sms.strategy.SmsStrategy;
import com.xingyuv.captcha.model.common.ResponseModel;
import com.xingyuv.captcha.model.vo.CaptchaVO;
import com.xingyuv.captcha.service.CaptchaService;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.net.InetSocketAddress;
import java.net.Proxy;
import java.time.Duration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.shop.zkmall.app.utils.TencentCloudEmailUtil.sendTemplateEmail;


/**
 * 客户登录
 *
 * @author zkmall zkmallvip@163.com
 */
@Slf4j
@RestController
@RequestMapping("app")
@RequiredArgsConstructor
@Tag(name = "客户登录模块", description = "客户登录模块")
public class LoginController {

    private final HttpServletRequest request;

    private final RedisTemplate<String, Object> redisTemplate;

    private final RedisService redisService;

    private final IndexService indexService;

    private final CereBuyerUserService cereBuyerUserService;

    private final CereProductSkuService cereProductSkuService;

    private final CerePlatformShopService cerePlatformShopservice;

    private final CerePlatformDictService cerePlatformDictService;

    private final UserRedisService userRedisService;

    private final CereBuyerSearchService cereBuyerSearchService;

    private final SmsStrategy smsStrategy;

    private final CaptchaService captchaService;

    private final TxTemplate txTemplate;

    @Value("${defaultHeadImg}")
    private String defaultHeadImg;

    private static final String APP_ID = "1072792244795667";
    private static final String APP_SECRET = "87d21f64a3a1d6456b4790846ee33a4a";



    /**
     * 登录 Facebook
     */
    @GetMapping("/loginWithFacebook")
    public R<?> loginWithFacebook(@RequestParam String accessToken) {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 7890)); // 按你的代理端口改
        factory.setProxy(proxy);
        factory.setConnectTimeout(5000);
        factory.setReadTimeout(5000);
        // 1️⃣ 验证 access_token 是否有效 1194980252696991
        String appAccessToken = APP_ID + "|" + APP_SECRET;
        String debugUrl = "https://graph.facebook.com/debug_token" +
                "?input_token=" + accessToken +
                "&access_token=" + appAccessToken;
        RestTemplate restTemplate = new RestTemplate(factory);
        Map debugResponse = restTemplate.getForObject(debugUrl, Map.class);
        Map<String, Object> data = (Map<String, Object>) debugResponse.get("data");
        if (data == null || !(Boolean) data.get("is_valid")) {
            return R.fail("无效的 access_token");
        }

        // 3️⃣ 绑定或注册本地用户
        String facebookId = (String) data.get("user_id");
        //根据脸书id查询用户 若无则让用户绑定
        BuyerUser personal = cereBuyerUserService.loginByFaceBookId(facebookId);
        if (personal == null) {
            return R.warn("请绑定手机号");
        }
        //创建token并存储缓存
        TokenInfoBo tokenInfoBo = userRedisService.createToken(personal.getPhone(), personal.getBuyerUserId());
        personal.setToken(tokenInfoBo.getToken());
        personal.setRefreshToken(tokenInfoBo.getRefreshToken());
        return R.ok(personal);
    }




    @ApiOperation("脸书绑定")
    @RequestMapping(value = "/faceBookBand", method = RequestMethod.POST)
    @ResponseBody
    public Result<Void> faceBookBand(@RequestParam String faceBookId,
                                     @RequestParam String telephone,
                                     @RequestParam String authCode) {
        cereBuyerUserService.faceBookBand(faceBookId, telephone, authCode);
        return new Result<>();
    }


    /**
     * 手机号登录
     *
     * @param param 封装json对象
     */
    @PostMapping("login")
    @NoRepeatSubmit
    @Operation(summary = "手机号登录")
    public Result<BuyerUser> login(@RequestBody LoginParam param) {
        ValidationUtil.checkValidateCode(param.getPhone(), param.getVerificationCode());
        String ip = HttpUtils.getClientIp(request);
        //根据手机号查询客户信息
        BuyerUser personal = cereBuyerUserService.login(param);
            //登录
        if (personal != null) {
            cereBuyerUserService.updateLastLoginIp(personal.getBuyerUserId(), ip);
            if (IntegerEnum.NO.getCode().equals(personal.getState())) {
                return new Result<>(CoReturnFormat.USER_TYPE_STOP);
            }
            if (IntegerEnum.YES.getCode().equals(personal.getIfBlack())) {
                return new Result<>(CoReturnFormat.HAVE_BLACK);
            }
            //创建token并存储缓存
            TokenInfoBo tokenInfoBo = userRedisService.createToken(param.getPhone(), personal.getBuyerUserId());
            personal.setToken(tokenInfoBo.getToken());
            personal.setRefreshToken(tokenInfoBo.getRefreshToken());
        } else {
            return new Result<>(CoReturnFormat.USER_UNREGISTER);
        }
        return new Result<>(personal, CoReturnFormat.SUCCESS);
    }


    /**
     * 邮箱登录
     *
     * @param param 封装json对象
     */
    @PostMapping("loginByEmail")
    @NoRepeatSubmit
    @Operation(summary = "邮箱登录")
    public Result<BuyerUser> loginByEmail(@RequestBody LoginParam param) {
        String key = CacheKeyConstants.SEND_EMAIL_CODE_PREFIX + param.getEmail();
        ValidationUtil.checkValidateEmailCode(param.getEmail(), param.getEmailCode(),redisService.getCacheObject(key));
        String ip = HttpUtils.getClientIp(request);
        //根据邮箱查询客户信息
        //验证邮箱验证码
        BuyerUser personal = cereBuyerUserService.loginByEmail(param);
        //登录
        if (personal != null) {
            cereBuyerUserService.updateLastLoginIp(personal.getBuyerUserId(), ip);
            if (IntegerEnum.NO.getCode().equals(personal.getState())) {
                return new Result<>(CoReturnFormat.USER_TYPE_STOP);
            }
            if (IntegerEnum.YES.getCode().equals(personal.getIfBlack())) {
                return new Result<>(CoReturnFormat.HAVE_BLACK);
            }
            //创建token并存储缓存
            TokenInfoBo tokenInfoBo = userRedisService.createToken(param.getPhone(), personal.getBuyerUserId());
            personal.setToken(tokenInfoBo.getToken());
            personal.setRefreshToken(tokenInfoBo.getRefreshToken());
        } else {
            return new Result<>(CoReturnFormat.USER_UNREGISTER);
        }
        return new Result<>(personal, CoReturnFormat.SUCCESS);
    }


    /**
     * 用户注册
     *
     * @param param 封装json对象
     */
    @PostMapping("register")
    @NoRepeatSubmit
    @Operation(summary = "用户注册")
    public Result<BuyerUser> register(@RequestBody LoginParam param) {
        ValidationUtil.checkValidateCode(param.getPhone(), param.getVerificationCode());
        String ip = HttpUtils.getClientIp(request);
        //根据手机号查询客户信息
        BuyerUser personal = cereBuyerUserService.login(param);
        //注册
        if (personal != null) {
            return new Result<>(CoReturnFormat.USER_AREADY_REGISTER);
        } else {
            //新增用户
            CereBuyerUser cereBuyerUser = new CereBuyerUser();
            cereBuyerUser.setName("MJ" + RandomStringUtil.getRandomCode(5, 0));
            cereBuyerUser.setPhone(param.getPhone());
            cereBuyerUser.setPassword(EncryptUtil.encrypt("123456"));
            cereBuyerUser.setCreateTime(TimeUtils.yyMMddHHmmss());
            cereBuyerUser.setState(IntegerEnum.YES.getCode());
            cereBuyerUser.setIfBlack(IntegerEnum.NO.getCode());
            cereBuyerUser.setRegisterIp(ip);
            cereBuyerUser.setLastLoginIp(ip);
            //设置默认头像
            cereBuyerUser.setHeadImage(defaultHeadImg);
            cereBuyerUserService.insert(cereBuyerUser);
            //创建im用户
            txTemplate.accountImport(cereBuyerUser.getBuyerUserId().toString(), cereBuyerUser.getName(), cereBuyerUser.getHeadImage());
            personal = new BuyerUser();
            personal.setWechatName(cereBuyerUser.getName());
            personal.setToken(cereBuyerUser.getToken());
            personal.setPhone(cereBuyerUser.getPhone());
            personal.setBuyerUserId(cereBuyerUser.getBuyerUserId());
            //创建token并存储缓存
            TokenInfoBo tokenInfoBo = userRedisService.createToken(param.getPhone(), personal.getBuyerUserId());
            personal.setToken(tokenInfoBo.getToken());
            personal.setRefreshToken(tokenInfoBo.getRefreshToken());

        }
        return new Result<>(personal, CoReturnFormat.SUCCESS);
    }
    /**
     * 刷新token
     *
     * @param param 封装json对象
     */
    @PostMapping("refreshToken")
    @NoRepeatSubmit
    @Operation(summary = "刷新token")
    public Result<BuyerUser> refreshToken(@RequestBody RefreshTokenParam param) {
        TokenInfoBo tokenInfoBo = userRedisService.refreshToken(param.getRefreshToken());
        CereBuyerUser cereBuyerUser = cereBuyerUserService.selectByBuyerUserId(tokenInfoBo.getBuyerUserId());
        BuyerUser buyerUser = new BuyerUser();
        BeanUtils.copyProperties(cereBuyerUser, buyerUser);

        buyerUser.setToken(tokenInfoBo.getToken());
        buyerUser.setRefreshToken(tokenInfoBo.getRefreshToken());
        return new Result<>(buyerUser, CoReturnFormat.SUCCESS);
    }

    /**
     * 首页数据查询
     */
    @GetMapping("index")
    @Operation(summary = "首页数据查询")
    public Result<Index> index(IndexParam param, HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        CereBuyerUser user = null;
        if (!EmptyUtils.isEmpty(token)) {
            //根据token查询用户信息
            user = cereBuyerUserService.findByToken(token);
        }
        Index index = indexService.index(param, user);
        return new Result<>(index, CoReturnFormat.SUCCESS);
    }


    /**
     * 兴趣爱好选择
     */
    @PostMapping("choiceLike")
    @Operation(summary = "兴趣爱好选择")
    public R<?> choiceLike(@RequestBody LikeReq likeReq, HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        CereBuyerUser user = null;
        if (!EmptyUtils.isEmpty(token)) {
            //根据token查询用户信息
            user = cereBuyerUserService.findByToken(token);
        }
        cereBuyerUserService.choiceLike(user, likeReq);
        return R.ok();
    }

    /**
     * 历史搜索查询
     */
    @GetMapping("getHistory")
    @Operation(summary = "历史搜索查询")
    public Result<List<CereBuyerSearch>> getHistory(HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        CereBuyerUser user = null;
        if (!EmptyUtils.isEmpty(token)) {
            //根据token查询用户信息
            user = cereBuyerUserService.findByToken(token);
        }
        List<CereBuyerSearch> list = indexService.getHistory(user);
        return new Result<>(list, CoReturnFormat.SUCCESS);
    }

    /**
     * 商品搜索查询
     */
    @GetMapping("getSearchProducts")
    @Operation(summary = "商品搜索查询")
    public Result<Page<Product>> getSearchProducts(SearchParam param, HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        CereBuyerUser user = null;
        if (!EmptyUtils.isEmpty(token)) {
            //根据token查询用户信息
            user = cereBuyerUserService.findByToken(token);
        }
        Page<Product> page = indexService.getSearchProducts(param, user);
        return new Result<>(page, CoReturnFormat.SUCCESS);
    }

    /**
     * 删除搜索记录
     */
    @RequestMapping(value = "deleteSearch", method = {RequestMethod.DELETE, RequestMethod.POST})
    @Operation(summary = "删除搜索记录")
    public Result<String> deleteSearch(@RequestBody SearchParam param) {
        indexService.deleteSearch(param);
        return new Result<>(CoReturnFormat.SUCCESS);
    }

    @RequestMapping(value = "selectHotSearch")
    @Operation(summary = "查询热搜词")
    public Result<List<String>> selectHotSearch() {
        return new Result<>(cereBuyerSearchService.selectHotSearch(), CoReturnFormat.SUCCESS);
    }


    /**
     * 获取短信验证码
     */
    @GetMapping("getCode")
    @Operation(summary = "获取短信验证码")
    @NoRepeatSubmit
    public Result<String> getCode(@Validated BuyerGetCodeParam user) {
        //获取验证码
        String code = RandomStringUtil.getRandom();
        Map<String, String> map = new HashMap<>();
        map.put("code", code);
        String sendCodeKey = CacheKeyConstants.SEND_SMS_CODE_PREFIX + user.getPhone();
        if (redisTemplate.hasKey(sendCodeKey)) {
            log.warn("手机号{}重复获取短信验证码.", user.getPhone());
            return Result.fail(CoReturnFormat.SEND_CODE_ERR, "一分钟内禁止重复获取,请稍后再试!");
        }
        redisTemplate.opsForValue().set(sendCodeKey, code, Duration.ofMinutes(1));
        //验证码存到redis中(5分钟失效)
        redisTemplate.opsForValue().set(user.getPhone(), code, Duration.ofMinutes(5));
        //发送短信给用户
        try {
            smsStrategy.sendNotice(user.getPhone(), map);
        } catch (Exception e) {
            log.error("getCode fail: phone = {}", user.getPhone(), e);
            throw new CoBusinessException(CoReturnFormat.SYS_ERROR);
        }
        return new Result<>(CoReturnFormat.SUCCESS);
    }


    /**
     * 获取邮箱验证码
     */
    @GetMapping("getEmailCode")
    @Operation(summary = "获取邮箱验证码")
    @NoRepeatSubmit
    public Result<String> getEmailCode(@Validated BuyerGetCodeParam user) {
        String sendCodeKey = CacheKeyConstants.SEND_EMAIL_CODE_PREFIX + user.getEmail();
        if (redisTemplate.hasKey(sendCodeKey)) {
            log.warn("邮箱{}重复获取邮箱验证码.", user.getEmail());
            return Result.fail(CoReturnFormat.SEND_CODE_ERR, "一分钟内禁止重复获取,请稍后再试!");
        }

        String code = RandomUtil.randomNumbers(4);
        boolean result = sendTemplateEmail(user.getEmail(),
                156777, "{\"name\": \"张三\", \"code\": \""+code+"\"}", "【TalkThePrice】欢迎注册TalkThePrice");

        redisTemplate.opsForValue().set(sendCodeKey, code, Duration.ofMinutes(5));
        //验证码存到redis中(5分钟失效)
        return new Result<>(CoReturnFormat.SUCCESS);
    }

    /**
     * 初始化商品库存
     */
    @GetMapping("stock")
    @Operation(summary = "初始化商品库存")
    public Result<String> stock() {
        List<CereProductSku> skus = cereProductSkuService.findAll();
        if (!EmptyUtils.isEmpty(skus)) {
            skus.forEach(sku -> redisTemplate.opsForValue().set(String.valueOf(sku.getSkuId()), sku.getStockNumber()));
        }
        return new Result<>(CoReturnFormat.SUCCESS);
    }


}
